package factura.modelo.reportes;

import java.awt.Dimension;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFrame;

import factura.dao.HibernateUtilDAO;
import factura.modelo.Emisor;
import factura.modelo.xml.Factura;
import factura.modelo.xml.InfoTributaria;
import factura.util.TipoAmbienteEnum;
import factura.util.TipoEmisionEnum;
import factura.util.TipoImpuestoEnum;
import factura.util.TipoImpuestoIvaEnum;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.view.JRSaveContributor;
import net.sf.jasperreports.view.save.JRPdfSaveContributor;

public class ReporteUtil {
	private static final String DIR_SUCURSAL = "DIR_SUCURSAL";
	private static final String CONT_ESPECIAL = "CONT_ESPECIAL";
	private static final String LLEVA_CONTABILIDAD = "LLEVA_CONTABILIDAD";

	private static Emisor obtenerEmisor()  {

		try {
			return (Emisor) HibernateUtilDAO.findAll("Emisor").get(0);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		return null;
		}
		
	}

	public void generarReporte(String urlReporte, FacturaReporte fact,
			String numAut, String fechaAut) throws SQLException,
			ClassNotFoundException {
		FileInputStream is = null;
		try {
			JRDataSource dataSource = new JRBeanCollectionDataSource(
					fact.getDetallesAdiciones());
			is = new FileInputStream(urlReporte);
			JasperPrint reporte_view = JasperFillManager.fillReport(
					is,
					obtenerMapaParametrosReportes(
							obtenerParametrosInfoTriobutaria(fact.getFactura()
									.getInfoTributaria(), numAut, fechaAut),
							obtenerInfoFactura(fact.getFactura()
									.getInfoFactura(), fact)), dataSource);
			showReport(reporte_view);
			return;
		} catch (FileNotFoundException ex) {
			Logger.getLogger(ReporteUtil.class.getName()).log(Level.SEVERE,
					null, ex);
		} catch (JRException e) {
			Logger.getLogger(ReporteUtil.class.getName()).log(Level.SEVERE,
					null, e);
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException ex) {
				Logger.getLogger(ReporteUtil.class.getName()).log(Level.SEVERE,
						null, ex);
			}
		}
	}

	private Map<String, Object> obtenerMapaParametrosReportes(
			Map<String, Object> mapa1, Map<String, Object> mapa2) {
		mapa1.putAll(mapa2);
		return mapa1;
	}

	private Map<String, Object> obtenerParametrosInfoTriobutaria(
			InfoTributaria infoTributaria, String numAut, String fechaAut)
			throws SQLException, ClassNotFoundException {
		Map<String, Object> param = new HashMap();
		param.put("RUC", infoTributaria.getRuc());
		param.put("CLAVE_ACC", infoTributaria.getClaveAcceso());
		param.put("RAZON_SOCIAL", infoTributaria.getRazonSocial());
		param.put("DIR_MATRIZ", infoTributaria.getDirMatriz());
		try {
			if ((obtenerEmisor().getLogoimagen() != null)
					&& (!obtenerEmisor().getLogoimagen().isEmpty())) {
				param.put("LOGO", new FileInputStream(obtenerEmisor()
						.getLogoimagen()));
			} else {
				param.put("LOGO", new FileInputStream(
						"resources/images/logo.jpeg"));
			}
		} catch (FileNotFoundException ex) {
			try {
				param.put("LOGO", new FileInputStream(
						"resources/images/logo.jpeg"));
				Logger.getLogger(ReporteUtil.class.getName()).log(Level.SEVERE,
						null, ex);
			} catch (FileNotFoundException ex1) {
				Logger.getLogger(ReporteUtil.class.getName()).log(Level.SEVERE,
						null, ex1);
			}
		}
		param.put("SUBREPORT_DIR", "resources/reportes/");
		param.put("TIPO_EMISION", obtenerTipoEmision(infoTributaria));
		param.put("NUM_AUT", numAut);
		param.put("FECHA_AUT", fechaAut);
		param.put("MARCA_AGUA", obtenerMarcaAgua(infoTributaria.getAmbiente()));
		param.put("NUM_FACT",
				infoTributaria.getEstab() + "-" + infoTributaria.getPtoEmi()
						+ "-" + infoTributaria.getSecuencial());
		param.put("AMBIENTE", obtenerAmbiente(infoTributaria));
		param.put("NOM_COMERCIAL", infoTributaria.getNombreComercial());
		return param;
	}

	private String obtenerAmbiente(InfoTributaria infoTributaria) {
		if (infoTributaria.getAmbiente().equals("2")) {
			return TipoAmbienteEnum.PRODUCCION.toString();
		}
		return TipoAmbienteEnum.PRUEBAS.toString();
	}

	private String obtenerTipoEmision(InfoTributaria infoTributaria) {
		if (infoTributaria.getTipoEmision().equals("2")) {
			return TipoEmisionEnum.CONTINGENCIA.getCode();
		}
		if (infoTributaria.getTipoEmision().equals("1")) {
			return TipoEmisionEnum.NORMAL.getCode();
		}
		return null;
	}

	private InputStream obtenerMarcaAgua(String ambiente) {
		try {
			if (ambiente.equals(TipoAmbienteEnum.PRODUCCION.getCode())) {
				return new BufferedInputStream(new FileInputStream(
						"resources/images/produccion.jpeg"));
			}
			return new BufferedInputStream(new FileInputStream(
					"resources/images/pruebas.jpeg"));
		} catch (FileNotFoundException fe) {
			Logger.getLogger(ReporteUtil.class.getName()).log(Level.SEVERE,
					null, fe);
		}
		return null;
	}

	private Map<String, Object> obtenerInfoFactura(
			Factura.InfoFactura infoFactura, FacturaReporte fact) {
		Map<String, Object> param = new HashMap();
		param.put("DIR_SUCURSAL", infoFactura.getDirEstablecimiento());
		param.put("CONT_ESPECIAL", infoFactura.getContribuyenteEspecial());
		param.put("LLEVA_CONTABILIDAD", infoFactura.getObligadoContabilidad());
		param.put("RS_COMPRADOR", infoFactura.getRazonSocialComprador());
		param.put("RUC_COMPRADOR", infoFactura.getIdentificacionComprador());
		param.put("FECHA_EMISION", infoFactura.getFechaEmision());
		param.put("GUIA", infoFactura.getGuiaRemision());
		TotalComprobante tc = getTotales(infoFactura);
		param.put("VALOR_TOTAL", infoFactura.getImporteTotal());
		param.put("DESCUENTO", infoFactura.getTotalDescuento());
		param.put("IVA", tc.getIva12());
		param.put("IVA_0", tc.getSubtotal0());
		param.put("IVA_12", tc.getSubtotal12());
		param.put("EXENTO_IVA", tc.getSubtotalExentoIVA());
		param.put("ICE", tc.getTotalIce());
		param.put("IRBPNR", tc.getTotalIRBPNR());
		param.put("NO_OBJETO_IVA", tc.getSubtotalNoSujetoIva());
		param.put("SUBTOTAL", infoFactura.getTotalSinImpuestos());
		if (infoFactura.getPropina() != null) {
			param.put("PROPINA", infoFactura.getPropina().toString());
		}
		param.put("TOTAL_DESCUENTO", calcularDescuento(fact));
		return param;
	}

	private String calcularDescuento(FacturaReporte fact) {
		BigDecimal descuento = new BigDecimal(0);
		for (DetallesAdicionalesReporte detalle : fact.getDetallesAdiciones()) {
			descuento = descuento.add(new BigDecimal(detalle.getDescuento()));
		}
		return descuento.toString();
	}

	private TotalComprobante getTotales(Factura.InfoFactura infoFactura) {
		BigDecimal totalIva12 = new BigDecimal(0.0D);
		BigDecimal totalIva0 = new BigDecimal(0.0D);
		BigDecimal totalExentoIVA = new BigDecimal(0.0D);
		BigDecimal iva12 = new BigDecimal(0.0D);
		BigDecimal totalICE = new BigDecimal(0.0D);
		BigDecimal totalIRBPNR = new BigDecimal(0.0D);
		BigDecimal totalSinImpuesto = new BigDecimal(0.0D);
		TotalComprobante tc = new TotalComprobante();
		for (Factura.InfoFactura.TotalConImpuestos.TotalImpuesto ti : infoFactura
				.getTotalConImpuestos().getTotalImpuesto()) {
			Integer cod = new Integer(ti.getCodigo());
			if ((TipoImpuestoEnum.IVA.getCode() == cod.intValue())
					&& (TipoImpuestoIvaEnum.IVA_VENTA_12.getCode().equals(ti
							.getCodigoPorcentaje()))) {
				totalIva12 = totalIva12.add(ti.getBaseImponible());
				iva12 = iva12.add(ti.getValor());
			}
			if ((TipoImpuestoEnum.IVA.getCode() == cod.intValue())
					&& (TipoImpuestoIvaEnum.IVA_VENTA_0.getCode().equals(ti
							.getCodigoPorcentaje()))) {
				totalIva0 = totalIva0.add(ti.getBaseImponible());
			}
			if ((TipoImpuestoEnum.IVA.getCode() == cod.intValue())
					&& (TipoImpuestoIvaEnum.IVA_NO_OBJETO.getCode().equals(ti
							.getCodigoPorcentaje()))) {
				totalSinImpuesto = totalSinImpuesto.add(ti.getBaseImponible());
			}
			if ((TipoImpuestoEnum.IVA.getCode() == cod.intValue())
					&& (TipoImpuestoIvaEnum.IVA_EXCENTO.getCode().equals(ti
							.getCodigoPorcentaje()))) {
				totalExentoIVA = totalExentoIVA.add(ti.getBaseImponible());
			}
			if (TipoImpuestoEnum.ICE.getCode() == cod.intValue()) {
				totalICE = totalICE.add(ti.getValor());
			}
			if (TipoImpuestoEnum.IRBPNR.getCode() == cod.intValue()) {
				totalIRBPNR = totalIRBPNR.add(ti.getValor());
			}
		}
		tc.setIva12(iva12.toString());
		tc.setSubtotal0(totalIva0.toString());
		tc.setSubtotal12(totalIva12.toString());
		tc.setTotalIce(totalICE.toString());
		tc.setSubtotal(totalIva0.add(totalIva12));
		tc.setSubtotalExentoIVA(totalExentoIVA);
		tc.setTotalIRBPNR(totalIRBPNR);
		tc.setSubtotalNoSujetoIva(totalSinImpuesto.toString());
		return tc;
	}

	public void showReport(JasperPrint jp) {
		JasperViwerSRI jv = new JasperViwerSRI(jp, Locale.getDefault());
		List<JRSaveContributor> newSaveContributors = new LinkedList();
		JRSaveContributor[] saveContributors = jv.getSaveContributors();
		for (int i = 0; i < saveContributors.length; i++) {
			if ((saveContributors[i] instanceof JRPdfSaveContributor)) {
				newSaveContributors.add(saveContributors[i]);
			}
		}
		jv.setSaveContributors((JRSaveContributor[]) newSaveContributors
				.toArray(new JRSaveContributor[0]));
		JFrame jf = new JFrame();
		jf.setTitle("Generador de RIDE");
		jf.getContentPane().add(jv);
		jf.validate();
		jf.setVisible(true);
		jf.setSize(new Dimension(800, 650));
		jf.setLocation(300, 100);
		jf.setDefaultCloseOperation(1);
	}
}
